import TurnJsError from "./TurnJsError";
// Processes classes

export function dec(that, methods, args) {
  if (!args[0] || typeof args[0] == "object")
    return methods.init.apply(that, args);
  else if (methods[args[0]])
    return methods[args[0]].apply(that, Array.prototype.slice.call(args, 1));
  else throw new TurnJsError(args[0] + " is not a method or property");
}

// Attributes for a layer

export function divAtt(top, left, zIndex, overf) {
  return {
    css: {
      position: "absolute",
      top: top,
      left: left,
      overflow: overf || "hidden",
      zIndex: zIndex || "auto",
    },
  };
}

// Gets a 2D point from a bezier curve of four points

export function bezier(p1, p2, p3, p4, t) {
  var a = 1 - t,
    b = a * a * a,
    c = t * t * t;

  return point2D(
    Math.round(
      b * p1.x + 3 * t * a * a * p2.x + 3 * t * t * a * p3.x + c * p4.x
    ),
    Math.round(
      b * p1.y + 3 * t * a * a * p2.y + 3 * t * t * a * p3.y + c * p4.y
    )
  );
}

// Converts an angle from degrees to radians

export function rad(degrees) {
  return (degrees / 180) * Math.PI;
}

// Converts an angle from radians to degrees

export function deg(radians) {
  return (radians / Math.PI) * 180;
}

// Gets a 2D point

export function point2D(x, y) {
  return { x: x, y: y };
}

// Returns the traslate value

export function translate(x, y, use3d) {
  return use3d
    ? " translate3d(" + x + "px," + y + "px, 0px) "
    : " translate(" + x + "px, " + y + "px) ";
}

// Returns the rotation value

export function rotate(degrees) {
  return " rotate(" + degrees + "deg) ";
}

// Checks if a property belongs to an object

export function has(property, object) {
  return Object.prototype.hasOwnProperty.call(object, property);
}

export const autoprefix = (styles, insertBefore = true) => {
  const fields = ["-moz-", "-webkit-", "-o-", "-ms-"];
  return Object.entries(styles).reduce(
    (prev, [key, value]) => ({
      ...prev,
      ...fields.reduce(
        (obj, field) => ({
          ...obj,
          [(insertBefore ? field : "") + key]:
            (!insertBefore ? field : "") + value,
        }),
        {}
      ),
    }),
    {}
  );
};

// Gradients

export function gradient(obj, p0, p1, colors, numColors) {
  var j,
    cols = [];

  // if (vendor == "-webkit-") {
  //   for (j = 0; j < numColors; j++)
  //     cols.push("color-stop(" + colors[j][0] + ", " + colors[j][1] + ")");

  //   obj.css({
  //     "background-image":
  //       "-webkit-gradient(linear, " +
  //       p0.x +
  //       "% " +
  //       p0.y +
  //       "%," +
  //       p1.x +
  //       "% " +
  //       p1.y +
  //       "%, " +
  //       cols.join(",") +
  //       " )",
  //   });
  // } else {
  p0 = { x: (p0.x / 100) * obj.width(), y: (p0.y / 100) * obj.height() };
  p1 = { x: (p1.x / 100) * obj.width(), y: (p1.y / 100) * obj.height() };

  var dx = p1.x - p0.x,
    dy = p1.y - p0.y,
    angle = Math.atan2(dy, dx),
    angle2 = angle - Math.PI / 2,
    diagonal =
      Math.abs(obj.width() * Math.sin(angle2)) +
      Math.abs(obj.height() * Math.cos(angle2)),
    gradientDiagonal = Math.sqrt(dy * dy + dx * dx),
    corner = point2D(
      p1.x < p0.x ? obj.width() : 0,
      p1.y < p0.y ? obj.height() : 0
    ),
    slope = Math.tan(angle),
    inverse = -1 / slope,
    x =
      (inverse * corner.x - corner.y - slope * p0.x + p0.y) / (inverse - slope),
    c = { x: x, y: inverse * x - inverse * corner.x + corner.y },
    segA = Math.sqrt(Math.pow(c.x - p0.x, 2) + Math.pow(c.y - p0.y, 2));

  for (j = 0; j < numColors; j++)
    cols.push(
      " " +
        colors[j][1] +
        " " +
        ((segA + gradientDiagonal * colors[j][0]) * 100) / diagonal +
        "%"
    );

  obj.css(
    autoprefix(
      {
        "background-image":
          "linear-gradient(" + -angle + "rad," + cols.join(",") + ")",
      },
      false
    )
  );
  // }
}

// Triggers an event

export function trigger(eventName, context, args) {
  var event = window.$.Event(eventName);
  context.trigger(event, args);
  if (event.isDefaultPrevented()) return "prevented";
  else if (event.isPropagationStopped()) return "stopped";
  else return "";
}

// Find the offset of an element ignoring its transformation

export function findPos(obj) {
  var offset = { top: 0, left: 0 };

  do {
    offset.left += obj.offsetLeft;
    offset.top += obj.offsetTop;
  } while ((obj = obj.offsetParent));

  return offset;
}

// Checks if there's hard page compatibility
// IE9 is the only browser that does not support hard pages

export function hasHardPage() {
  return navigator.userAgent.indexOf("MSIE 9.0") == -1;
}
